<template>
  <el-tree
    ref="el"
    style="width: 100%"
    v-bind="props"
    :default-checked-keys="valueModel"
    :data="treeData"
    v-on="$listeners"
    @check="handleCheck"
  />
</template>

<script>
import Vue from 'vue';
import {Tree} from "element-ui";
import {cloneJson} from "@/utils";

Vue.use(Tree);

/**
 * 树形组件,element-ui的[el-tree](https://element.eleme.cn/2.13/#/zh-CN/component/tree)
 * @author maolin
 */
export default {
  name: "ErpFormTree",
  components: {
  },
  props: {
    /**
     * 标题
     * @public
     */
    title: {
      type: String,
      default: '',
    },
    /**
     * 字段名
     * @public
     */
    field: {
      type: String,
      default: ''
    },
    /**
     * 默认值
     * @public
     */
    value: {
      default () {
        return '';
      }
    },
    /**
     * 默认选项
     * @public
     */
    options: {
      type: Array,
      default() {
        return [];
      }
    },
    /**
     * 树组件的配置[el-tree](https://element.eleme.cn/2.13/#/zh-CN/component/tree#props)
     */
    props: {
      type: Object,
      default () {
        return {
        };
      }
    },
    /**
     * 额外配置项，
     * ```js
     * return {
     * // 所有项都禁用
          allDisabled: false,
       // 通过字符串函数设置是否全部禁用
          allDisabledFunction: ""
        }
     * ```
     * @public
     */
    extra: {
      type: Object,
      default () {
        return {
          allDisabled: false,
          allDisabledFunction: ""
        };
      }
    }
  },
  computed: {
    treeData () {
      if (this.disabledTree()) {
        if (this.options) {
          return this.addDisabledToTree(cloneJson(this.options));
        }
        return [];
      } else {
        return this.options;
      }
    },
    valueModel: {
      get () {
        let value = this.value;
        let valueArr = value ? value.split(',') : [];
        let arr = valueArr.filter((item) => {
          let tree = this.getTreeByValue(item, this.treeData, this.labelKey, this.childrenKey, this.valueKey);
          return !!(tree && (!tree[this.childrenKey] || tree[this.childrenKey].length === 0));
        });
        return arr;
      },
      set (val) {
        this.$emit('value-change', val);
      }
    },
    labelKey (){
      return this.props && this.props.props && this.props.props.label ? this.props.props.label : "label";
    },
    childrenKey (){
      return this.props && this.props.props && this.props.props.children ? this.props.props.children : "children";
    },
    valueKey () {
      return this.props && this.props.nodeKey ? this.props.nodeKey : "value";
    },
    allDisabled () {
      return this.extra && this.extra.allDisabled === true;
    },
    allDisabledFunction () {
      return this.extra && this.extra.allDisabledFunction ? this.extra.allDisabledFunction : "";
    }
  },
  watch: {
  },
  mounted() {
  },
  methods: {
    /**
     * 选中树中某一项
     * @private
     */
    handleCheck (item, checkedObj) {
      let checkedKey = checkedObj && checkedObj.checkedKeys ? checkedObj.checkedKeys : [];
      let halfCheckedKey = this.$refs.el.getHalfCheckedKeys();
      checkedKey = checkedKey.concat(halfCheckedKey);
      this.valueModel = checkedKey && checkedKey.length > 0 ? checkedKey.join(',') : '';
    },
    /**
     * 判断是否禁用树的复选框
     * @private
     */
    disabledTree () {
      if (this.allDisabledFunction) {
        try{
          return new Function(this.allDisabledFunction)();
        }catch (e) {
          return false;
        }
      } else {
        return this.allDisabled;
      }
    },
    /**
     *
     * @private
     */
    addDisabledToTree (tree) {
      if (tree && tree.length > 0) {
        for (let i in tree) {
          if (tree[i].disabled === undefined) {
            tree[i].disabled = true;
          }
          if (tree[i][this.childrenKey] && tree[i][this.childrenKey].length > 0) {
            tree[i][this.childrenKey] = this.addDisabledToTree(tree[i][this.childrenKey]);
          }
        }
      }
      return tree;
    },
    /**
     * 通过树结构中的某个属性的唯一值获取树结构的某一个对象
     * @private
     */
    getTreeByValue (value, treeData, labelKey, childrenKey,  valueKey) {
      let tree = null;
      return rec(value, treeData, labelKey, childrenKey, valueKey);
      function rec (value, treeData, labelKey, childrenKey, valueKey) {
        if (!treeData) return null;
        for (let i = 0; i < treeData.length; i ++) {
          if (treeData[i][valueKey] == value) {
            tree = treeData[i];
            break;
          }
          if (treeData[i][childrenKey] && treeData[i][childrenKey].length > 0) {
            rec(value, treeData[i][childrenKey],  labelKey, childrenKey,  valueKey);
          }
        }
        return tree;
      }
    }
  }
};
</script>

<style lang="scss" scoped>
    $fontSize: var(--font-size);
    ::v-deep{
        .el-tree-node__label{
            font-size: $fontSize;
        }
    }
</style>
